package com.readExcelImage;

import com.readExcelImage.bean.*;
import org.apache.poi.ooxml.util.PackageHelper;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.jdom2.*;
import org.jdom2.input.SAXBuilder;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class ReadExcelUtil {
    public static Map<String, ExcelImageInfo> readAllImage(InputStream xlsxInputStream){
        try {
            OPCPackage opc = PackageHelper.open(xlsxInputStream);
            return handle(opc);
        } catch (IOException | InvalidFormatException | JDOMException e) {
            throw new RuntimeException(e);
        }
    }
    public static Map<String, ExcelImageInfo> readAllImage(String  xlsFilePath) throws IOException {
        return readAllImage(Files.newInputStream(new File(xlsFilePath).toPath()));
    }

    private static Map<String,ExcelImageInfo> handle(OPCPackage opc) throws IOException, InvalidFormatException, JDOMException {
        //获取所有包文件
        List<PackagePart> parts = opc.getParts();
        //获取每个工作表中的包文件
        Map<String, PackagePart> collect = parts.stream().collect(Collectors.toMap(packagePart -> packagePart.getPartName().getName(), packagePart -> packagePart));
        W_WorkBook allSheetInfo = getAllSheetInfo(collect);
        W_WorkSheets wWorkSheets = getAllSheetContent(collect);
        W_CellImages_XML_Rels allCellImageRelsInfo = getAllCellImageRelsInfo(collect);
        W_CellImages_XML allCellImages = getAllCellImages(collect);
        List<ExcelImageInfo> imageInfos = new ArrayList<>();
        for (W_CellImage wCellImage : allCellImages.getWCellImages().getCellImagList()) {
            ExcelImageInfo excelImageInfo = new ExcelImageInfo();
            String dispimgId = wCellImage.getDISPIMG_ID();
            String fileID = wCellImage.getFileID();
            String fileName = wCellImage.getFileName();
            excelImageInfo.setDISPIMG_id(dispimgId);
            excelImageInfo.setFileId(fileID);
            excelImageInfo.setOriginFileName(fileName);
            imageInfos.add(excelImageInfo);
        }
        Map<String, ExcelImageInfo> collectRes = imageInfos.stream().collect(Collectors.toMap(ExcelImageInfo::getDISPIMG_id, excelImageInfo -> excelImageInfo));

        for (W_Relationship wRelationship : allCellImageRelsInfo.getWRelationships().getWRelationshipList()) {
            String id = wRelationship.getId();
            String target = wRelationship.getTarget();
            for (Map.Entry<String, ExcelImageInfo> entry : collectRes.entrySet()) {
                ExcelImageInfo excelImageInfo = entry.getValue();
                String fileId = excelImageInfo.getFileId();
                if (fileId.equals(id)) {
                    excelImageInfo.setLocationStr(target);
                }
            }
        }
        for (W_WorkSheet wWorkSheet : wWorkSheets.getWWorkSheets()) {
            String originSheetName = wWorkSheet.getSheetName();
            String sheetIndex = originSheetName.replace("sheet", "");
            for (W_ImageContent wImageContent : wWorkSheet.getWSheetData().getWImageContents()) {
                String dispImg_id = extractImgId(wImageContent.getDISPIMG_ID());
                ExcelImageInfo excelImageInfo = collectRes.get(dispImg_id);
                if (excelImageInfo != null) {
                    excelImageInfo.setSheetIndex(Integer.parseInt(sheetIndex) - 1);
                    if (excelImageInfo.getWPoints() == null) {
                        List<W_Point> wPoints1 = new ArrayList<>();
                        excelImageInfo.setWPoints(wPoints1);
                    }
                    List<W_Point> wPoints = excelImageInfo.getWPoints();
                    W_Point wPoint = new W_Point();
                    wPoint.setPointStr(wImageContent.getPointStr());
                    wPoints.add(wPoint);
                }
            }
        }
        for (W_Sheet wSheet : allSheetInfo.getWSheets().getWSheets()) {
            int sheetIndex = wSheet.getSheetIndex();

            for (Map.Entry<String, ExcelImageInfo> entry : collectRes.entrySet()) {
                ExcelImageInfo value = entry.getValue();
                int sheetIndex1 = value.getSheetIndex();
                if (sheetIndex1 == sheetIndex) {
                    value.setSheetName(wSheet.getName());
                }
            }
        }
        for (Map.Entry<String, ExcelImageInfo> entry : collectRes.entrySet()) {
            for (Map.Entry<String, PackagePart> packagePartEntry : collect.entrySet()) {
                if (packagePartEntry.getValue().getPartName().getName().contains(entry.getValue().getLocationStr())) {
                    // 存储PackagePart引用而不是InputStream
                    entry.getValue().setImagePart(packagePartEntry.getValue());
//                    InputStream inputStream = packagePartEntry.getValue().getInputStream();
//                    entry.getValue().setImageInputStream(inputStream);
                }
            }
        }
        return collectRes;
    }
    // 读取  /xl/workbook.xml 信息，包含 sheet 信息
    private static W_WorkBook getAllSheetInfo(Map<String, PackagePart> collect) throws IOException, JDOMException {
        W_WorkBook wWorkBook = new W_WorkBook();
        W_Sheets wSheets = new W_Sheets();
        List<W_Sheet> wSheetss = new ArrayList<>();
        PackagePart packagePart = collect.get("/xl/workbook.xml");
        // 定义命名空间 URI 和前缀
        String namespaceURI = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
        String prefix = "r";
        // 创建命名空间对象
        Namespace namespaceURI_r = Namespace.getNamespace(prefix, namespaceURI);
        // 定义默认命名空间 URI 和前缀
        String defaultNamespaceURI = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
        String prefixMain = "main"; // 前缀可以是任意的，因为它只在你的Java代码中使用
        Namespace namespaceMain = Namespace.getNamespace(prefixMain, defaultNamespaceURI);

        Document doc = new SAXBuilder().build(packagePart.getInputStream());
        Element rootElement = doc.getRootElement();
        List<Element> sheetsList = rootElement.getChildren("sheets", namespaceMain);
        Element firstSheets = sheetsList.get(0);
        List<Element> sheetList = firstSheets.getChildren("sheet", namespaceMain);
        for (Element sheet : sheetList) {
            W_Sheet wSheet = new W_Sheet();
            String sheetId = sheet.getAttribute("sheetId").getValue();
            int sheetIndex = Integer.parseInt(sheetId) - 1;
            wSheet.setName(sheet.getAttribute("name").getValue());
            wSheet.setSheetId(sheetId);
            wSheet.setSheetIndex(sheetIndex);
            wSheet.setRID(sheet.getAttribute("id", namespaceURI_r).getValue());
            wSheetss.add(wSheet);
        }
        wSheets.setWSheets(wSheetss);
        wWorkBook.setWSheets(wSheets);
        return wWorkBook;
    }

    // 读取 /xl/worksheets/sheet 的内容
    private static W_WorkSheets getAllSheetContent(Map<String, PackagePart> collect) throws IOException, JDOMException {
        // 定义默认命名空间 URI 和前缀     http://schemas.openxmlformats.org/spreadsheetml/2006/main
        String defaultNamespaceURI = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
        Namespace namespaceMain = Namespace.getNamespace("", defaultNamespaceURI);
        W_WorkSheets wWorkSheets = new W_WorkSheets();
        List<W_WorkSheet> w_workSheetList = new ArrayList<>();
        for (String name : collect.keySet()) {
            if (name.contains("/xl/worksheets/sheet")) {
                W_WorkSheet wWorkSheet = new W_WorkSheet();
                String sheetNoStr = name.replace("/xl/worksheets/sheet", "").replace(".xml", "");
                int sheetNo = Integer.parseInt(sheetNoStr);
                wWorkSheet.setSheetName("sheet" + sheetNo);
                W_SheetData wSheetData = new W_SheetData();
                List<W_ImageContent> imageContents = new ArrayList<>();
                PackagePart packagePart = collect.get(name);
                // 获取文档
                Document doc = new SAXBuilder().build(packagePart.getInputStream());
                Element rootElement = doc.getRootElement();
                List<Element> sheetData = rootElement.getChildren("sheetData", namespaceMain);
                Element sheetDataFirst = sheetData.get(0);
                List<Element> rows = sheetDataFirst.getChildren("row", namespaceMain);
                for (Element row : rows) {
                    List<Element> cs = row.getChildren("c", namespaceMain);
                    for (Element c : cs) {
                        List<Element> vs = c.getChildren("v", namespaceMain);
                        if (vs.size()==0){
                            continue;
                        }
                        Element v = vs.get(0);
                        String value = v.getValue();
                        boolean contains = value.contains("=DISPIMG");
                        if (contains) {
                            W_ImageContent imageContent = new W_ImageContent();
                            imageContent.setPointStr(c.getAttribute("r").getValue());
                            imageContent.setDISPIMG_ID(v.getValue());
                            imageContents.add(imageContent);
                        }
                    }
                }
                wSheetData.setWImageContents(imageContents);
                wWorkSheet.setWSheetData(wSheetData);
                w_workSheetList.add(wWorkSheet);
            }
        }
        wWorkSheets.setWWorkSheets(w_workSheetList);
        return wWorkSheets;
    }

    // 读取 /xl/_rels/cellimages.xml.rels 的内容
    private static W_CellImages_XML_Rels getAllCellImageRelsInfo(Map<String, PackagePart> collect) throws IOException, JDOMException {
        W_CellImages_XML_Rels wCellImagesXmlRels = new W_CellImages_XML_Rels();
        W_Relationships wRelationships = new W_Relationships();
        List<W_Relationship> wRelationshipList = new ArrayList<>();
        PackagePart part = collect.get("/xl/_rels/cellimages.xml.rels");
        SAXBuilder builder = new SAXBuilder();
        // 获取文档
        Document doc = builder.build(part.getInputStream());
        // 获取根节点
        Element root = doc.getRootElement();
        List<Element> relationshipList = root.getChildren();
        for (Element relationship : relationshipList) {
            W_Relationship wRelationship = new W_Relationship();
            String id = relationship.getAttributeValue("Id");
            String target = relationship.getAttributeValue("Target");
            wRelationship.setId(id);
            wRelationship.setTarget(target);
            wRelationshipList.add(wRelationship);
        }
        wRelationships.setWRelationshipList(wRelationshipList);
        wCellImagesXmlRels.setWRelationships(wRelationships);
        return wCellImagesXmlRels;
    }

    // 读取 /xl/cellimages.xml 的内容
    private static W_CellImages_XML getAllCellImages(Map<String, PackagePart> collect) throws IOException, JDOMException {
        W_CellImages_XML wCellImagesXml = new W_CellImages_XML();
        W_CellImages wCellImages = new W_CellImages();
        List<W_CellImage> wCellImageList = new ArrayList<>();
        PackagePart part = collect.get("/xl/cellimages.xml");
        SAXBuilder builder = new SAXBuilder();
        // 获取文档
        Document doc = builder.build(part.getInputStream());
        // 获取根节点
        Element root = doc.getRootElement();
        List<Element> cellImageList = root.getChildren();
        for (Element imgEle : cellImageList) {
            W_CellImage wCellImage = new W_CellImage();
            Element xdrPic = imgEle.getChildren().get(0);
            Element xdrNvPicPr = xdrPic.getChildren().get(0);
            Element xdrBlipFill = xdrPic.getChildren().get(1);
            Element aBlip = xdrBlipFill.getChildren().get(0);
            Attribute attr = aBlip.getAttributes().get(0);
            String imgId = xdrNvPicPr.getChildren().get(0).getAttributeValue("name");
            String fileName = xdrNvPicPr.getChildren().get(0).getAttributeValue("descr");
            String id = xdrNvPicPr.getChildren().get(0).getAttributeValue("id");
            String fileID = attr.getValue();
            wCellImage.setId(id);
            wCellImage.setFileID(fileID);
            wCellImage.setDISPIMG_ID(imgId);
            wCellImage.setFileName(fileName);
            wCellImageList.add(wCellImage);
        }
        wCellImages.setCellImagList(wCellImageList);
        wCellImagesXml.setWCellImages(wCellImages);
        return wCellImagesXml;
    }

    /**
     * 从给定的字符串中解析出ID。
     *
     * @param input 输入的字符串，格式为 =DISPIMG("ID_HERE",number)
     * @return 提取出的ID字符串
     */
    private static String extractImgId(String input) {
        // 正则表达式，用于匹配 =DISPIMG("ID",数字) 格式的字符串
        String regex = "=DISPIMG\\(\"([^\"]+)\"\\,([^)]+)\\)";
        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(regex);
        java.util.regex.Matcher matcher = pattern.matcher(input);

        if (matcher.find()) {
            // 如果找到匹配项，则返回第一个捕获组中的内容，即ID
            return matcher.group(1);
        } else {
            // 如果没有找到匹配项，返回null或抛出异常，取决于你的需求
            return null;
        }
    }
}
